Auto merge of #5037 - Eh2406:conflict_tracking, r=alexcrichton
authorbors <bors@rust-lang.org>
Wed, 14 Feb 2018 16:52:47 +0000 (16:52 +0000)
committerbors <bors@rust-lang.org>
Wed, 14 Feb 2018 16:52:47 +0000 (16:52 +0000)
commit489f570d47dea88d8f9a1205173d3e779e1a78e2
treef0e01d13ff259da0986a8e18a1d6e39abba72a96
parente2c5d2e65a3705f48ee960b7c773487b9b9077a5
parent889909342cd9342babe2ca738d2d81c639a38050
Auto merge of #5037 - Eh2406:conflict_tracking, r=alexcrichton

Conflict tracking

This is an alternative implementation of #4834. This is slower but hopefully more flexible and clearer. The idea is to keep a list of `PackageId`'s that have caused us to skip a `Candidate`. Then we can use the list when we are backtracking if any items in our list have not been activated then we will have new `Candidate`'s to try so we should stop backtracking. Or to say that another way; We can continue backtracking as long as all the items in our list is still activated.

Next this new framework was used to make the error messages more focused. We only need to list the versions that conflict, as opposed to all previously activated versions.

Why is this more flexible?
1. It is not limited to conflicts within the same package. If `RemainingCandidates.next` skips something  because of a links attribute, that is easy to record, just add the `PackageId` to the set `conflicting_prev_active`.
2. Arbitrary things can add conflicts to the backtracking. If we fail to activate because some dependency needs a feature that does not exist, that is easy to record, just add the `PackageId` to the set `conflicting_activations`.
3. All things that could cause use to fail will be in the error messages, as the error messages loop over the set.
4. With a simple extension, replacing the `HashSet` with a `HashMap<_, Reason>`, we can customize the error messages to show the nature of the conflict.

@alexcrichton, @aidanhs, Does the logic look right? Does this seem clearer to you?